﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Windows.Forms;

using Cards.Util;
using Cards.GUI;

namespace Cards.Objects
{
    public class CVNPockerStage : CStage
    {
        public CVNPockerStage(INS_Stage _insStage) : base(_insStage)
        {
        }

        //Thuc hien luot danh
        public override void Play(Boolean _fromNetwork = false, int _id = -1)
        {
            try
            {
                int i = 0;
                int lenArr = 0;
                ArrayList tmpArr = new ArrayList();
                ArrayList tmpPreArr = new ArrayList();

                if (m_insStage.m_currentCard.Count != 0)
                {
                    tmpPreArr = (ArrayList)m_insStage.m_currentCard.Clone();
                }

                INS_Player insPlayer_tmp = m_insStage[INS_Stage.sSide];
                for (i = 0; i < 13; i++)
                {
                    if ((insPlayer_tmp[i].SELECT == 1) && (!insPlayer_tmp[i].CARD.PLAY))
                    {
                        tmpArr.Add(insPlayer_tmp[i]);
                    }
                }

                lenArr = tmpArr.Count;

                if (!CheckRule_VNPocker.CheckPlayedCard(tmpArr)
                || !CheckRule_VNPocker.CheckCardGreater(tmpArr, tmpPreArr, INS_Stage.sFirstPlayingPlayer,
                                            insPlayer_tmp))
                {
                    if (m_insStage[INS_Stage.sSide].PLAYERKIND == PLAYER_TYPE.COMPUTER)
                    {
                        m_insStage[INS_Stage.sSide].DeselectAllCards();
                        m_insStage[INS_Stage.sSide].ReceiveTurn();
                    }
                    else
                    {
                        IS.IPC.ShowMessage("Quân bài đánh không hợp lệ!");
                    }
                    return;
                }
                else if (MainFrame.sFirstPlayInStage)
                {
                    if (MainFrame.s_numOfPlayers == Constants.VNPOCKER_MAX_PLAYERS)
                    {
                        if (!ArrayUtil.FindCardByCardType(tmpArr, Constants.BABICH))
                        {
                            if (m_insStage[INS_Stage.sSide].PLAYERKIND == PLAYER_TYPE.COMPUTER)
                            {
                                m_insStage[INS_Stage.sSide].DeselectAllCards();
                                m_insStage[INS_Stage.sSide].ReceiveTurn();
                            }
                            else
                            {
                                IS.IPC.ShowMessage("Quân bài đánh đầu tiên phải có 3 bích!");
                            }
                            return;
                        }
                    }
                    else
                    {
                        int minValue = ArrayUtil.FindMinCard(m_insStage[INS_Stage.sSide]);
                        if (!ArrayUtil.FindCardByCardType(tmpArr, minValue))
                        {
                            if (m_insStage[INS_Stage.sSide].PLAYERKIND == PLAYER_TYPE.COMPUTER)
                            {
                                m_insStage[INS_Stage.sSide].DeselectAllCards();
                                m_insStage[INS_Stage.sSide].ReceiveTurn();
                            }
                            else
                            {
                                IS.IPC.ShowMessage("Lượt đánh đầu tiên phải có quân nhỏ nhất!");
                            }
                            return;
                        }
                    }
                }

                //Hop le
                MainFrame.sFirstPlayInStage = false;

                insPlayer_tmp.PLAYER.NOTMOVE = false;
                insPlayer_tmp.PLAYER.SKIP = false;

                m_insStage.m_currentCard.Clear();
                m_insStage.m_currentCard = (ArrayList)tmpArr.Clone();

                if (m_insStage.m_previousCard.Count != 0)
                {
                    m_insStage.m_previousCard.Clear();
                }
                m_insStage.m_previousCard = (ArrayList)tmpPreArr.Clone();
                MovePlayedCardsToTable(m_insStage.m_previousCard);

                if (INS_Stage.sBeginPlaying)
                {
                    INS_Stage.sBeginPlaying = false;
                }

                MovePlayedCards(m_insStage.m_currentCard);
                ShrinkCards();


                /////////////////////////////////////////////////////////////////
                // Two case of network playing: a move at the server and a move from client
                String msgToSend = BuildAMessageMove(INS_Stage.sSide, tmpArr);
                if (_fromNetwork)
                {
                    if (MainFrame.s_isServer)
                    {
                        // Server broadcast a move from network client to the others clients
                        MainFrame.m_frmMultiGame.MULTIGAME.SendAMove(msgToSend, _id);
                    }
                }
                else
                {
                    if (MainFrame.s_multiType != MULTI_PLAYER_TYPE.SINGLE_PLAYER)
                    {
                        // Server broadcast a move from network client to the others clients
                        MainFrame.m_frmMultiGame.MULTIGAME.SendAMove(msgToSend);
                    }
                }
                ////////////////////////////////////////////


                INS_Stage.sFirstPlayingPlayer = insPlayer_tmp;

                if (CheckRule_VNPocker.CheckWin(insPlayer_tmp))
                {
                    ((CVNPockerPlayer)insPlayer_tmp.PLAYER).Win();
                    m_insStage.arrivedPlayers.Add(m_insStage[INS_Stage.sSide]);

                    INS_VNPockerStage.sWinPlayerPos = INS_Stage.sSide;
                    INS_VNPockerStage.sWin = true;

                    if (INS_VNPockerStage.sWinPos == 1)
                    {
                        INS_VNPockerStage.sFirstWinPlayer = INS_Stage.sSide;
                        int count = CheckWinOrLose();
                        if (count == INS_VNPockerStage.sRemainPlayers)
                        {
                            for (i = 0; i < IS.NUMPLAYERS; i++)
                            {
                                if (!m_insStage[i].PLAYER.WIN)
                                {
                                    ((CVNPockerPlayer)m_insStage[i].PLAYER).Win();
                                }
                            }
                            m_insStage.EndStage();
                            return;
                        }
                        INS_VNPockerStage.sRemainPlayers -= count;
                    }

                    if (INS_VNPockerStage.sRemainPlayers == 1)
                    {
                        long tmp = 0;
                        for (i = 0; i < IS.NUMPLAYERS; i++)
                        {
                            if (!m_insStage[i].PLAYER.WIN || (m_insStage[i].PLAYER.WINPOS == IS.NUMPLAYERS))
                            {
                                // calculate lose money of 1st lose player
                                tmp = INS_VNPockerStage.sBetMoney * 2 + ((CVNPockerPlayer)m_insStage[i].PLAYER).ExtraBillLose();
                                m_insStage[i].PLAYER.WINMONEY = 0;
                                m_insStage[i].PLAYER.AMOUNT_DECREASE_MONEY = tmp;
                                m_insStage[i].PLAYER.AMOUNT_INCREASE_MONEY = 0;
                            }
                            if (m_insStage[i].PLAYER.WINPOS == (IS.NUMPLAYERS - 1))
                            {
                                // calculate lose money of 2st lose player
                                //m_insStage[i].PLAYER.WINMONEY -= INS_VNPockerStage.sBetMoney;
                            }
                        }
                        m_insStage.EndStage();
                        return;
                    }
                }

                INS_VNPockerStage.sPreviousTurnPlayer = INS_Stage.sSide;

                if (MainFrame.s_multiType == MULTI_PLAYER_TYPE.SINGLE_PLAYER)
                {
                    if (m_insStage[INS_Stage.sSide].PLAYERKIND == PLAYER_TYPE.COMPUTER) //computer
                    {
                        ((INS_VNPockerPlayer)m_insStage[INS_Stage.sSide]).HidePlayedCardPicOfComputer(lenArr);
                    }
                }
                else
                {
                    if ((m_insStage[INS_Stage.sSide].PLAYERKIND == PLAYER_TYPE.COMPUTER) ||
                        ((m_insStage[INS_Stage.sSide].PLAYERKIND == PLAYER_TYPE.HUMAN)
                        && (m_insStage[INS_Stage.sSide].STT != MainFrame.m_frmMultiGame.GAMEPLAYERID - 1)))
                    {
                        ((INS_VNPockerPlayer)m_insStage[INS_Stage.sSide]).HidePlayedCardPicOfComputer(lenArr);
                    }
                }


                // Clear the temp array cards
                tmpArr.Clear();
                tmpPreArr.Clear();

                GiveAwayTurn();

            }
            catch (SystemException se)
            {
                MessageBox.Show(se.Message);
            }
        }

        /// <summary>
        /// Build message to send for a move on network
        /// </summary>
        /// <param name="_id"></param>
        /// <param name="_arr"></param>
        /// <returns></returns>
        public String BuildAMessageMove(int _id, ArrayList _arr)
        {
            String str = "";

            try
            {
                str += _id;
                str += NetworkConstants.MESSAGETYPE_SEPARATOR;

                for (int i = 0; i < _arr.Count; i++)
                {
                    INS_Card ic = (INS_Card)_arr[i];
                    if (ic != null)
                    {
                        if (i > 0)
                        {
                            str += NetworkConstants.MESSAGETYPE_SUBSEPARATOR;
                        }
                        str += ic.CARD.CARDTYPE;
                    }
                }
            }
            catch (SystemException se)
            {
                MessageBox.Show(se.Message);
            }

            return str;
        }

        /// <summary>
        /// Move the played cards of previous player to the table
        /// </summary>
        /// <param name="_arrayOfCards"></param>
        public void MovePlayedCardsToTable(ArrayList _arrayOfCards)
        {
            //m_insStage.IPC.RemoveCards();
            int count = m_insStage.IPC.CARDSARRAY.Count;
            for (int i = 0; i < _arrayOfCards.Count; i++)
            {
                m_insStage.IPC.CARDSARRAY.Add(new INS_Card((INS_Card)_arrayOfCards[i]));
                HideCards(_arrayOfCards);
            }
            m_insStage.IPC.DisplayCards(count);
        }

        //Hide quan bai da danh
        public void HideCards(ArrayList _arrayOfCards)
        {
            for (int i = 0; i < _arrayOfCards.Count; i++)
            {
                ((INS_Card)_arrayOfCards[i]).HideCards();
            }
        }

        public override void Skip(Boolean _fromNetwork = false, int _id = -1)
        {
            ((INS_VNPockerPlayer)m_insStage[INS_Stage.sSide]).SkipPlaying();
            m_insStage[INS_Stage.sSide].PLAYER.SKIP = true;
            INS_VNPockerStage.sSkippedPlayers++;

            /////////////////////////////////////////////////////////////////
            // Two case: a move at the server and a skip from client
            String msgToSend = "";
            msgToSend += INS_Stage.sSide;

            if (_fromNetwork)
            {
                if (MainFrame.s_isServer)
                {
                    // Server broadcast a skip from network client to the others clients
                    MainFrame.m_frmMultiGame.MULTIGAME.SendASkip(msgToSend, _id);
                }
            }
            else
            {
                if (MainFrame.s_multiType != MULTI_PLAYER_TYPE.SINGLE_PLAYER)
                {
                    // Server broadcast a skip from network client to the others clients
                    MainFrame.m_frmMultiGame.MULTIGAME.SendASkip(msgToSend);
                }
            }
            ////////////////////////////////////////////

            GiveAwayTurn();
        }

        public void StartNewCycle()
        {
            INS_VNPockerStage.sLoseRate = 1;
            INS_VNPockerStage.sSkippedPlayers = 0;
            INS_VNPockerStage.sBeginPlaying = true;

            m_insStage.IPC.RemoveCards();
            ResetArrayOfPlayedCards();

            for (int i = 0; i < IS.NUMPLAYERS; i++)
            {
                if (i != INS_Stage.sSide)
                {
                    m_insStage[i].EndTurn();
                    if (!m_insStage[i].PLAYER.WIN)
                    {
                        m_insStage[i].SetStateText("");
                    }
                }

                if (m_insStage[i].PLAYER.WINPOS == 0)
                {
                    m_insStage[i].PLAYER.SKIP = false;
                }
            }
        }

        public void ResetArrayOfPlayedCards()
        {
            HideCards(m_insStage.m_currentCard);
            m_insStage.m_currentCard.Clear();
            m_insStage.m_previousCard.Clear();
        }

        //Chuyen luot di cho nguoi choi ke tiep
        public void GiveAwayTurn()
        {
            int i = INS_Stage.sSide;
            while (true)
            {
                if (i != INS_Stage.sSide)
                {
                    INS_Stage.sSide++;
                    if (INS_Stage.sSide == IS.NUMPLAYERS)
                    {
                        INS_Stage.sSide = 0;
                    }

                    if ((((CPlayer)m_insStage[INS_Stage.sSide].PLAYER).WINPOS == 0 &&
                        !((CPlayer)m_insStage[INS_Stage.sSide].PLAYER).SKIP)
                        )
                    {
                        m_insStage[INS_Stage.sSide].ReceiveTurn();
                        break;
                    }
                    else if ((CheckRule_VNPocker.CheckPigs(m_insStage.m_currentCard)
                                || CheckRule_VNPocker.CheckPine(m_insStage.m_currentCard)
                                || CheckRule_VNPocker.Check4CardsOfKind(m_insStage.m_currentCard))
                             && ((CVNPockerPlayer)m_insStage[INS_Stage.sSide].PLAYER).Check4Fines())
                    {
                        if (m_insStage[INS_Stage.sSide].PLAYER.SKIP)
                        {
                            INS_VNPockerStage.sSkippedPlayers--;
                            m_insStage[INS_Stage.sSide].PLAYER.SKIP = false;
                        }
                        m_insStage[INS_Stage.sSide].ReceiveTurn();
                        break;
                    }
                    else if (m_insStage.arrivedPlayers != null && m_insStage.arrivedPlayers.Count > 0)
                    {
                        if (m_insStage.arrivedPlayers.Contains(m_insStage[INS_Stage.sSide]))
                        {
                            m_insStage.arrivedPlayers.Remove(m_insStage[INS_Stage.sSide]);

                            INS_Stage.sSide++;
                            if (INS_Stage.sSide == IS.NUMPLAYERS)
                            {
                                INS_Stage.sSide = 0;
                            }

                            if (m_insStage.arrivedPlayers.Contains(m_insStage[INS_Stage.sSide]))
                            {
                                INS_Stage.sSide++;
                                if (INS_Stage.sSide == IS.NUMPLAYERS)
                                {
                                    INS_Stage.sSide = 0;
                                }
                            }

                            if (INS_VNPockerStage.sSkippedPlayers >= INS_VNPockerStage.sRemainPlayers)
                            {
                                StartNewCycle();
                                m_insStage[INS_Stage.sSide].ReceiveTurn();
                                break;
                            }
                            else if (INS_VNPockerStage.sSkippedPlayers == INS_VNPockerStage.sRemainPlayers - 1)
                            {
                                while (m_insStage[INS_Stage.sSide].PLAYER.SKIP)
                                {
                                    INS_Stage.sSide++;
                                    if (INS_Stage.sSide == IS.NUMPLAYERS)
                                    {
                                        INS_Stage.sSide = 0;
                                    }
                                }
                                StartNewCycle();
                                m_insStage[INS_Stage.sSide].ReceiveTurn();
                                break;
                            }
                        }
                    }
                }
                else
                {
                    m_insStage[i].EndTurn();
                    m_insStage[i].Skip();
                }
                i++;
            }
        }

        public void MovePlayedCards(ArrayList _arrayOfCards)
        {
            for (int i = 0; i < _arrayOfCards.Count; i++)
            {
                ((INS_Card)_arrayOfCards[i]).X = Constants.s_avatarWidth +
                                               i * Constants.s_space_bw_two_cards;
                ((INS_Card)_arrayOfCards[i]).Y = (((INS_Card)_arrayOfCards[i]).IP.YSTART -
                                                    Constants.s_cardHeight - 25) * (-1);
                ((INS_Card)_arrayOfCards[i]).Play();
            }
        }

        public void ShrinkCards()
        {
            m_insStage[INS_Stage.sSide].ShrinkCards();
        }

        //Co nguoi toi 1 nhung co nguoi chua danh duoc quan bai nao
        public int CheckWinOrLose()
        {
            int vtToi = IS.NUMPLAYERS;
            int count = 0;
            for (int i = 0; i < IS.NUMPLAYERS; i++)
            {
                if (m_insStage[i].STT != INS_Stage.sSide)
                {
                    if (m_insStage[i].PLAYER.NOTMOVE)
                    {
                        m_insStage[i].PLAYER.WINPOS = vtToi;
                        m_insStage[i].PLAYER.WIN = true;
                        //INS_Stage.sRemainPlayers--;
                        m_insStage[i].SetStateText("Thua trắng");
                        MessageBox.Show("Người chơi " + (i + 1) + " đã bị thua trắng");
                        m_insStage[i].DisplayCards();
                        m_insStage[i].PLAYER.WINMONEY = 0;
                        m_insStage[i].PLAYER.AMOUNT_INCREASE_MONEY = 0;
                        m_insStage[i].PLAYER.AMOUNT_DECREASE_MONEY = INS_VNPockerStage.sBetMoney * 3
                                                          + ((CVNPockerPlayer)m_insStage[i].PLAYER).ExtraBillLose();
                        m_insStage[INS_VNPockerStage.sFirstWinPlayer].PLAYER.WINMONEY +=
                                    INS_VNPockerStage.sBetMoney * 3 + ((CVNPockerPlayer)m_insStage[i].PLAYER).ExtraBillLose();
                        count++;
                    }
                }
            }
            return count;
        }

        public Boolean NoPigMore()
        {
            int count = 0;
            for (int i = 0; i < IS.NUMPLAYERS; i++)
            {
                for (int j = 0; j < Constants.VNPOCKER_NUMOFCARDS; j++)
                {
                    if (m_insStage[i][j].CARD.CARDVALUE == Constants.GT_HEO &&
                        !m_insStage[i][j].CARD.PLAY)
                    {
                        count++;
                    }
                }
            }

            if (count > 0)
            {
                return false;
            }
            return true;
        }
    }
}
